local PANEL = {}

AccessorFunc( PANEL, "m_bSizeToContents", 		"AutoSize" )
AccessorFunc( PANEL, "m_bBackground", 			"DrawBackground" )
AccessorFunc( PANEL, "m_bNoSizing", 			"NoSizing" )

AccessorFunc( PANEL, "Spacing", 	"Spacing" )
AccessorFunc( PANEL, "Padding", 	"Padding" )

/*---------------------------------------------------------
   Name: Init
---------------------------------------------------------*/
function PANEL:Init()
	self.pnlCanvas 	= vgui.Create( "Panel", self )
	self.pnlCanvas.OnMousePressed = function( self, code ) self:GetParent():OnMousePressed( code ) end
	self.pnlCanvas:SetMouseInputEnabled( true )
	self.pnlCanvas.InvalidateLayout = function() self:InvalidateLayout() end
	
	self.Items = {}
	self.XOffset = 0
	
	self:SetSpacing( 0 )
	self:SetPadding( 0 )
	self:SetAutoSize( false )
	self:SetDrawBackground( true )
	self:SetNoSizing( false )
	
	self:SetMouseInputEnabled( true )
	
	self:SetPaintBackgroundEnabled( false )
	self:SetPaintBorderEnabled( false )
end

/*---------------------------------------------------------
   Name: SizeToContents
---------------------------------------------------------*/
function PANEL:SizeToContents()
	self:SetSize( self.pnlCanvas:GetSize() )
end

/*---------------------------------------------------------
   Name: GetItems
---------------------------------------------------------*/
function PANEL:GetItems()
	return self.Items
end

/*---------------------------------------------------------
   Name: EnableVerticalScrollbar
---------------------------------------------------------*/
function PANEL:EnableHorizontalScrollbar()

	if (self.HBar) then return end
	
	self.HBar = vgui.Create( "DHScrollBar", self )
	
end

/*---------------------------------------------------------
   Name: GetCanvas
---------------------------------------------------------*/
function PANEL:GetCanvas()

	return self.pnlCanvas

end

/*---------------------------------------------------------
   Name: GetCanvas
---------------------------------------------------------*/
function PANEL:Clear( bDelete )

	for k, panel in pairs( self.Items ) do
	
		if ( panel && panel:IsValid() ) then
		
			panel:SetParent( panel )
			panel:SetVisible( false )
		
			if ( bDelete ) then
				panel:Remove()
			end
			
		end
		
	end
	
	self.Items = {}

end

/*---------------------------------------------------------
   Name: AddItem
---------------------------------------------------------*/
function PANEL:AddItem( item )

	if (!item || !item:IsValid()) then return end

	item:SetVisible( true )
	item:SetParent( self:GetCanvas() )
	table.insert( self.Items, item )
	
	self:InvalidateLayout()

end

/*---------------------------------------------------------
   Name: RemoveItem
---------------------------------------------------------*/
function PANEL:RemoveItem( item, bDontDelete )

	for k, panel in pairs( self.Items ) do
	
		if ( panel == item ) then
		
			self.Items[ k ] = nil
			
			if (!bDontDelete) then
				panel:Remove()
			end
		
			self:InvalidateLayout()
		
		end
	
	end

end

/*---------------------------------------------------------
   Name: Rebuild
---------------------------------------------------------*/
function PANEL:Rebuild()
	local Offset = 0
	
	local x, y = self.Padding, self.Padding;
	for k, panel in pairs( self.Items ) do
		if ( panel:IsVisible() ) then
			local w = panel:GetWide()
			local h = panel:GetTall()
                                
			panel:SetPos( x, y )
                
			x = x + w + self.Spacing
			Offset = w + x + self.Spacing 
		end
	end
	
	self:GetCanvas():SetWide( Offset + (self.Padding) - self.Spacing ) 
	
	// Although this behaviour isn't exactly implied, center vertically too
	if ( self.m_bNoSizing && self:GetCanvas():GetWide() < self:GetWide() ) then
		self:GetCanvas():SetPos( (self:GetWide()-self:GetCanvas():GetWide()) * 0.5, 0 )
	end
end

/*---------------------------------------------------------
   Name: OnMouseWheeled
---------------------------------------------------------*/
function PANEL:OnMouseWheeled( dlta )

	if ( self.HBar ) then
		return self.HBar:OnMouseWheeled( dlta )
	end
	
end

/*---------------------------------------------------------
   Name: Paint
---------------------------------------------------------*/
function PANEL:Paint()
	
	derma.SkinHook( "Paint", "PanelList", self )
	return true
	
end

/*---------------------------------------------------------
   Name: OnVScroll
---------------------------------------------------------*/
function PANEL:OnHScroll( iOffset )

	self.pnlCanvas:SetPos( iOffset, 0 )
	
end

/*---------------------------------------------------------
   Name: PerformLayout
---------------------------------------------------------*/
function PANEL:PerformLayout()

	local Tall = self:GetTall()
	local XPos = 0
	
	if ( !self.Rebuild ) then
		debug.Trace()
	end
	
	self:Rebuild()
	
	if ( self.HBar && !m_bSizeToContents ) then

		self.HBar:SetPos( 0, self:GetTall() - 16 )
		self.HBar:SetSize( self:GetWide(), 16 )
		self.HBar:SetLeft( self:GetWide(), self.pnlCanvas:GetWide() )
		XPos = self.HBar:GetOffset()
		
		if ( self.HBar.Enabled ) then Tall = Tall - 16 end

	end

	self.pnlCanvas:SetPos( XPos, 0 )
	self.pnlCanvas:SetTall( Tall )
	
	self:Rebuild()
	
	if ( self:GetAutoSize() ) then
	
		self:SetWide( self.pnlCanvas:GetWide() )
		self.pnlCanvas:SetPos( 0, 0 )
	
	end	

end

/*---------------------------------------------------------
   Name: OnMousePressed
---------------------------------------------------------*/
function PANEL:OnMousePressed( mcode )

	// Loop back if no VBar
	if ( !self.HBar && self:GetParent().OnMousePressed ) then
		return self:GetParent():OnMousePressed( mcode )
	end

	if ( mcode == MOUSE_RIGHT && self.HBar ) then
		self.HBar:Grip()
	end
	
end

function PANEL:SortByMember( key, desc )

	desc = desc or true

	table.sort( self.Items, function( a, b ) 

								if ( desc ) then
								
									local ta = a
									local tb = b
									
									a = tb
									b = ta
								
								end
	
								if ( a[ key ] == nil ) then return false end
								if ( b[ key ] == nil ) then return true end
								
								return a[ key ] > b[ key ]
								
							end )

end

derma.DefineControl( "DHorizontalPanelList", "A Panel that neatly organises other panels", PANEL, "Panel" )